<script setup lang="ts">
  import { computed, onMounted, ref } from 'vue'
  import { useBacktestStore } from '@/stores/backtestStore'
  import { useTradeStore } from '@/stores/tradeStore'

  const backtestStore = useBacktestStore()
  const tradeStore = useTradeStore()
  const selectedStrategy = ref('')
  const selectedOrderID = ref('')

  // 参数
  const selectCode = ref('')
  const selectWindow = ref('')
  const selectStartDate = ref('')
  const selectEndDate = ref('')
  const selectCash = ref('')
  const selectCommission = ref('')
  const selectHands = ref('')

  // 观察订单状态

  const get_strategyList = computed(() => {
    return backtestStore.strategyList.map(strategy => strategy.name)
  })

  const get_orderHistoryList = computed(() => {
    return tradeStore.orderHistoryList.map(orderHistory => orderHistory.orderID)
  })

  // 提示
  const snackbarStatus = ref(false)
  const snackbarMes = ref('')

  const show_snackBar = (mes: string) => {
    snackbarMes.value = mes
    snackbarStatus.value = true
  }

  // 查询订单
  const onHandleGetTradeHistoryBtnClick = async () => {
    snackbarMes.value = await tradeStore.getTradeHistory(selectedOrderID.value)
    snackbarStatus.value = true
  }

  // 删除订单
  const onHandleDeleteHistoryBtnClick = async () => {
    show_snackBar(await tradeStore.deleteHistory(selectedOrderID.value))
    selectedOrderID.value = ''
  }

  // 删除全部记录
  const onHandleDeleteAllHistory = async () => {
    show_snackBar(await tradeStore.deleteAllHistory())
    selectedOrderID.value = ''
  }

  // 处理回测按钮
  const onHandleBacktestBtnClick = async () => {
    const apiFunc = backtestStore.strategyApiMap[selectedStrategy.value]
    if (!apiFunc) {
      console.error('未找到对应策略的接口函数')
      return
    }
    // 获得策略的构造参数
    const paramsConfig = backtestStore.strategyParamsMap[selectedStrategy.value]
    if (!paramsConfig) {
      console.error('未找到对应策略的参数配置')
      return
    }

    show_snackBar('正在进行回测, 请稍后......')

    const paramObj: Record<string, string> = {}
    // 公共参数
    paramObj['code'] = selectCode.value
    paramObj['window'] = selectWindow.value
    paramObj['start_date'] = selectStartDate.value
    paramObj['end_date'] = selectEndDate.value
    paramObj['cash'] = selectCash.value
    paramObj['commission'] = selectCommission.value
    paramObj['hands'] = selectHands.value

    // 策略参数
    for (const item of paramsConfig) {
      paramObj[item.key] = item.value
    }

    const res = await apiFunc(paramObj)
    if (res.code === 1) {
      // 重新刷新订单记录
      await tradeStore.getOrderHistory()
      console.log(res.data)
    }
    show_snackBar(res.message)
  }

  // 说明
  const informationDialogStatus = ref(false)
  const onInformationChipClick = () => {
    informationDialogStatus.value = true
  }

  // 是否显示图表
  const is_showChart = computed(() => {
    return tradeStore.tradeHistoryList.length > 0
  })

  // 是否显示表格
  const is_showTable = computed(() => {
    return tradeStore.orderHistoryList.length > 0
  })

  const optionChart = computed(() => {
    const getSignalLabel = (signal: number): string => {
      if (signal === 1) return '买入'
      if (signal === -1) return '卖出'
      return '中性'
    }

    const list = tradeStore.tradeHistoryList ?? []

    const times = list.map(t => t.date_time)

    // 全部价格数据，折线用
    const priceLineData = list.map(item => ({
      value: [item.date_time, item.price],
      signal: item.signal,
      profit_cash: item.profit_cash,
      cash: item.cash,
      new_position: item.new_position,
      total_position: item.total_position,
    }))

    // 买卖信号点数据，只保留 signal != 0
    const signalPoints = list
      .filter(item => item.signal !== 0)
      .map(item => ({
        value: [item.date_time, item.price],
        signal: item.signal,
        profit_cash: item.profit_cash,
        cash: item.cash,
        new_position: item.new_position,
        total_position: item.total_position,
        itemStyle: {
          color: item.signal === 1 ? '#FF0000' : '#00FF00',
        },
        symbolSize: 10,
      }))

    const allYValues = list.map(t => t.price)
    const minY = Math.min(...allYValues)
    const maxY = Math.max(...allYValues)
    const yPadding = (maxY - minY) * 0.1 || 0.5

    return {
      grid: { top: '20%', left: '10%', right: '10%', bottom: '15%' },
      xAxis: {
        type: 'category',
        data: times,
        axisLabel: {
          fontSize: 12,
          color: '#FEFEFE',
          rotate: 45,
          interval: 0, // 显示所有标签位置
          formatter: (_val: string, idx: number) => {
            // 只显示signal != 0的时间，其他返回空字符串隐藏
            return list[idx]?.signal === 0 ? '' : times[idx]
          },
        },
        name: '时间',
        nameTextStyle: { fontSize: 14, color: '#FEFEFE', fontWeight: 'bold' },
      },
      yAxis: {
        type: 'value',
        name: '价格',
        min: Math.round((minY - yPadding) * 100) / 100,
        max: Math.round((maxY + yPadding) * 100) / 100,
        axisLabel: { fontSize: 14, color: '#FEFEFE' },
        nameTextStyle: { fontSize: 14, color: '#FEFEFE', fontWeight: 'bold' },
        splitLine: { lineStyle: { type: 'dashed', color: '#ddd' } },
      },
      legend: {
        data: ['实时价格', '买卖信号'],
        textStyle: { fontSize: 14, color: '#FEFEFE' },
        top: '5%',
      },
      tooltip: {
        trigger: 'item',
        formatter: (param: any) => {
          const d = param.data
          if (!d) return ''
          return `
          <div><strong>${d.value[0]}</strong></div>
          <div>价格: ${d.value[1]?.toFixed(2) ?? '-'}</div>
          <div>信号: ${getSignalLabel(d.signal)}</div>
          <div>盈亏: ${d.profit_cash ?? '-'}</div>
          <div>资金: ${d.cash ?? '-'}</div>
          <div>新仓: ${d.new_position ?? '-'}</div>
          <div>总仓: ${d.total_position ?? '-'}</div>
        `
        },
      },
      series: [
        {
          name: '实时价格',
          type: 'line',
          data: priceLineData,
          lineStyle: { width: 2, color: '#FFD700' },
          showSymbol: false, // 关闭默认symbol显示
          symbol: 'circle',
          symbolSize: (params: any) => (params?.data?.signal === 0 ? 0 : 10), // signal!=0显示点，signal=0不显示
          z: 10,
        },
        {
          name: '买卖信号',
          type: 'scatter',
          data: signalPoints,
          z: 20,
          tooltip: { show: true },
        },
      ],
    }
  })

  onMounted(() => {
    tradeStore.getOrderHistory()
  })
</script>

<template>
  <v-container>
    <v-row>
      <v-card
        class="w-100 ma-2"
        hover
        variant="outlined"
      >
        <v-row class="pa-2 align-center">
          <v-combobox
            v-model="selectedStrategy"
            class="ma-4"
            :items="get_strategyList"
            label="请选择相应的策略"
            variant="outlined"
          />
          <v-spacer />
          <v-chip
            class="mr-2"
            prepend-icon="mdi-information"
            @click="onInformationChipClick"
          >
            说明
          </v-chip>
          <v-dialog
            v-model="informationDialogStatus"
            transition="dialog-bottom-transition"
            width="auto"
          >

            <v-card
              prepend-icon="mdi-information"
              title="回测板块: "
            >
              <template #text>
                <p>&nbsp;&nbsp;&nbsp;&nbsp;回测板块是针对交易策略对于某个股票在某个时间段之内按照指定参数进行模拟交易, 在经过一定时间的计算之后, 会得出相应的<strong>交易订单记录</strong>, 可以查看此策略模拟交易的评估指标,
                  和详细的交易明细。</p>
                <br>
                <h2>参数说明: </h2>
                <h3>基本参数说明: </h3>
                <ul>
                  <li>
                    <strong>股票代码(code): 必填</strong> 填入需要模拟交易的股票代码 如: <em>000421</em>
                  </li>
                  <li>
                    <strong>时间窗口(window): 选填 默认为14天</strong> 填入需要参考的日期时间窗口 如: <em>14</em>
                  </li>
                  <li>
                    <strong>周期(period): 选填 默认为15分钟 可选:<em>15 30</em></strong> 填入当日历史价格记录的时间间隔 如: <em>15</em>
                  </li>
                  <li>
                    <strong>开始日期(start_date): 选填</strong> 填入模拟交易的开始日期 如: <em>20250701</em>
                  </li>
                  <li>
                    <strong>结束日期(end_date): 选填</strong> 填入模拟交易的结束日期日期 如: <em>20250730</em>
                  </li>
                </ul>
                <br>
                <h3>账户参数说明：</h3>
                <ul>
                  <li>
                    <strong>起始资金(cash): 选填 默认为10000</strong> 填入交易的初始资金 如: <em>5000</em>
                  </li>
                  <li>
                    <strong>佣金比例(commission): 选填 默认为0.001</strong> 填入交易的佣金比例 如: <em>0.03</em>
                  </li>
                  <li>
                    <strong>单次手数(hands): 选填 默认为1</strong> 填入交易的单次手数, 输入1即一次买入100股 如: <em>2</em>
                  </li>
                </ul>
                <br>
                <h2>评估指标说明: </h2>
                <ul>
                  <li>
                    <strong>收益率(profit_rate): </strong>是衡量投资回报的一个重要指标，表示一段时间内资产收益相对于其初始投入的比率。它能帮助我们判断投资是否赚钱、赚了多少。计算公式：<em>(剩余资产-初始资产) / 初始资产</em>
                  </li>
                </ul>
                <br>
                <h2>交易明细说明: </h2>
                <ol>
                  <li>
                    <strong>买入的价格: </strong>单次手数*100*当前价格+佣金(max(5, 比例))+过户费
                  </li>
                  <li>
                    <strong>卖出的价格: </strong>所有仓位*当前价格-佣金(max(5, 比例))-过户费-印花税
                  </li>
                </ol>
                <br>
                <h2>操作说明: </h2>
                <ol>
                  <li>
                    按参数说明填入对应的参数。
                  </li>
                  <li>
                    点击<strong>开始回测</strong>的按钮:
                    <p>
                      <img alt="" src="https://zhixuntrader-pic.oss-cn-shenzhen.aliyuncs.com/PixPin_2025-08-07_20-15-41.png" width="800">
                    </p>
                  </li>
                  <li>
                    等待一段时间后, 下方会出现提示, 同时订单表格会出现一条新的记录, 记录中包含<strong>订单号</strong>, <strong>交易的股票代码</strong>, <strong>交易发起的时间</strong>, <strong>使用的策略名</strong>和<strong>评估指标</strong>:
                    <p>
                      <img alt="" src="https://zhixuntrader-pic.oss-cn-shenzhen.aliyuncs.com/PixPin_2025-08-07_20-23-55.png" width="800">
                    </p>
                  </li>
                  <li>
                    <p>在下方选择想要查看的订单号, 点击查询订单: </p>
                    <p>
                      <img alt="" src="https://zhixuntrader-pic.oss-cn-shenzhen.aliyuncs.com/PixPin_2025-08-07_20-35-02.png" width="800">
                    </p>
                  </li>
                  <li>
                    <p>会出现该订单的交易明细, 包括<strong>交易记录图</strong>和<strong>交易记录表</strong>, <strong>交易记录图</strong>中红点代表买入, 绿点代表卖出, 把鼠标放上去会出现对应的信息;</p>
                    <p><strong>交易记录表</strong>则包含着每个时间间隔的交易状态, 详细的记录了<strong>当时的价格</strong>, <strong>买卖的信号</strong>, <strong>资金及其变化</strong>, 和<strong>仓位及其变化</strong>。</p>
                    <p>
                      <img alt="" src="https://zhixuntrader-pic.oss-cn-shenzhen.aliyuncs.com/pictures.jpg" width="800">
                    </p>
                  </li>
                </ol>
                <br>
                <h2>注意说明: </h2>
                <ol>
                  <li>参数设置中, 还有每个策略对应的参数, 在数据手册页面中具体说明。</li>
                </ol>
                <br>
                <h2><strong>按<em>ESC</em>退出此说明</strong></h2>
              </template>
            </v-card>
          </v-dialog>
          <v-btn class="me-4" prepend-icon="mdi-play" variant="outlined" @click="onHandleBacktestBtnClick">
            开始回测
          </v-btn>
        </v-row>
        <v-sheet
          border
          class="w-100"
          :elevation="1"
          rounded
        >
          <v-form>
            <v-container>
              <v-snackbar
                v-model="snackbarStatus"
              >
                {{ snackbarMes }}
                <template #actions>
                  <v-btn
                    color="pink"
                    variant="text"
                    @click="snackbarStatus = false"
                  >
                    Close
                  </v-btn>
                </template>
              </v-snackbar>
              <v-row>
                <v-chip variant="plain">
                  基本参数
                </v-chip>
              </v-row>
              <v-row>
                <v-col>
                  <v-text-field v-model="selectCode" label="股票代码" required variant="outlined" />
                </v-col>
                <v-col>
                  <v-text-field v-model="selectWindow" label="时间窗口" required variant="outlined" />
                </v-col>
                <v-col>
                  <v-text-field v-model="selectStartDate" label="开始日期" required variant="outlined" />
                </v-col>
                <v-col>
                  <v-text-field v-model="selectEndDate" label="结束日期" required variant="outlined" />
                </v-col>
              </v-row>
              <v-row>
                <v-chip variant="plain">
                  账户参数
                </v-chip>
              </v-row>
              <v-row>
                <v-col>
                  <v-text-field v-model="selectCash" label="起始资金" required variant="outlined" />
                </v-col>
                <v-col>
                  <v-text-field v-model="selectCommission" label="佣金比例" required variant="outlined" />
                </v-col>
                <v-col>
                  <v-text-field v-model="selectHands" label="单次手数" required variant="outlined" />
                </v-col>
              </v-row>
              <v-row v-if="selectedStrategy">
                <v-chip variant="plain">
                  策略参数
                </v-chip>
              </v-row>
              <v-row v-if="selectedStrategy">
                <v-col
                  v-for="(param, index) in backtestStore.strategyParamsMap[selectedStrategy]"
                  :key="index"
                >
                  <v-text-field
                    v-model="param.value"
                    :label="param.label"
                    variant="outlined"
                  />
                </v-col>
              </v-row>
              <v-row>
                <v-chip variant="plain">
                  订单记录
                </v-chip>
              </v-row>
              <v-row v-if="is_showTable">
                <v-data-table :fixed-header="true" :items="tradeStore.orderHistoryList" style="height: 440px;" />
              </v-row>
            </v-container>
          </v-form>
        </v-sheet>
      </v-card>
    </v-row>

    <v-row>
      <v-card
        class="w-100 ma-2"
        hover
        variant="outlined"
      >
        <v-row class="pa-2 align-center">
          <v-combobox
            v-model="selectedOrderID"
            class="ma-4"
            :items="get_orderHistoryList"
            label="请选择订单号"
            variant="outlined"
          />
          <v-spacer />
          <v-btn class="me-4" prepend-icon="mdi-magnify" variant="outlined" @click="onHandleGetTradeHistoryBtnClick">
            查询订单
          </v-btn>
          <v-btn class="me-4" prepend-icon="mdi-close-circle" variant="outlined" @click="onHandleDeleteHistoryBtnClick">
            删除订单记录
          </v-btn>
          <v-btn class="me-4" prepend-icon="mdi-backspace" variant="outlined" @click="onHandleDeleteAllHistory">
            删除全部记录
          </v-btn>
        </v-row>
        <v-sheet
          v-if="is_showChart"
          border
          class="w-100"
          :elevation="1"
          rounded
        >
          <v-container>
            <v-row>
              <v-chip variant="plain">
                交易记录
              </v-chip>
            </v-row>
            <v-row>
              <e-charts class="w-100" :option="optionChart" style="height: 800px;" />
            </v-row>
            <v-divider class="mt-4 mb-4" thickness="2" />
            <v-row>
              <v-data-table :fixed-header="true" :items="tradeStore.tradeHistoryList" style="height: 500px;" />
            </v-row>
          </v-container>
        </v-sheet>
      </v-card>
    </v-row>
  </v-container>
</template>

<style scoped lang="scss">

</style>
